<?php
/**
* Copyright 2009 Waag Society <http://www.waag.org>
* This file is part of Annotrax.
*
* Annotrax is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* Annotrax is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Annotrax.
* If not, see http://www.gnu.org/licenses/gpl.html
*/

?>
<?php
/**
 * Implements a simple pager
 *
 * A pager is a series of links that may be used to "paginate" over a list
 * of search results, such as produced by mysql 'limit' and 'offset' queries.
 *
 * @todo this class renders a very simple list of links. Maybe they should be more decorated?
 * @author Matthijs van Henten <matthijs@waag.org>
 */
class Zend_View_Helper_Pager{
	const PAGER_LIMIT 	= 15;
	const PAGER_MAX		= 25;
	const PAGER_OFFSET 	= 0;

	private $max;
	private $uri;
	private $offset;
	private $limit;

	/**
	 * This function is used as a pseudo constructor by Zend_View
	 * and may be called as a function.
	 *
	 * @param array $args An array containing the properties for this pager
	 * 		The __set method is used to parse the variables
	 *
	 * 	@return string $pager HTML code for the pager
	 */
	public function Pager( array $args = array() ){
		foreach( $args as $key => $value ){
			$this->__set( $key, $value );
		}

		return $this->getPager();
	}

	/**
	 * Render this pager by casting it to string
	 */
	public function __toString(){
		return $this->getPager();
	}

	/**
	 * Set a property of this class, use a setter method if implemented
	 *
	 * @param string $key Name of the property
	 * @param mixed $value Value to be set
	 *
	 * @return void
	 */
	public function __set( $key, $value ){
		if( property_exists( $this, $key ) ){
			if( ( $method = sprintf('set%s', ucfirst($key) ) )
			   && method_exists( $this, $method ) ){
				call_user_func( array( $this, $method ), $value );
			}
			else{
				$this->$key = $value;
			}
		}
	}

	/**
	 * Retrieve property, using a getter if implemneted
	 *
	 * @param string $key Name of the property
	 */
	public function __get( $key ){
		if( property_exists( $this, $key ) ){
			if( ( $method = sprintf( 'get%s' . ucfirst($key) ) ) && method_exists( $this, $method ) ){
				return call_user_func( array( $this, $method ) );
			}
			return $this->$key;
		}
	}

	/**
	 * Explicit render of the pager
	 *
	 * @return string $HTML Html code for this pager
	 */
	public function getPager(){
		if( $this->getMax() <= $this->getLimit() ){
			return;
		}


		$range = range( 0, $this->getMax()-1, $this->getLimit() );

		$offset = $this->getOffset();
		$bound = ( $offset - $offset % $this->getLimit() ); // normalize for unreliable offset

		$uri   = explode( '?', $this->getUri() );
		foreach( $range as $index ){
			$limit		= $index + $this->getLimit();
			$content	= sprintf('%d - %d', $index+1, $limit );

			$query = sprintf( 'offset=%d&limit=%d', $index, $this->getLimit() );
			if( isset( $uri[1] ) ){
				$query = $uri[1] . '&' . $query;
			}


			$attributes = array(
				'class' => 'pagerLink',
				'href'	=> sprintf( '%s/?%s', rtrim($uri[0], '/'), $query )
			);

			if( ($index+1) > $bound && $index < ( $bound + $this->getLimit() ) ){
				$attributes['class'] .= ' pagerCurrent';
			}

			$collect[] = $this->getHTML( 'a', $content, $attributes );
		}
		return join( ' | ', $collect );
	}

	/**
	 * render a single HTML string using a variable tagname, content and attributes
	 *
	 * @param string $tagName Something of a HTML tagName such as 'div'
	 * @param string $content Content to put into the tags
	 * @param array $attributes A key_value pair of attributes
	 *
	 * @return string $HTML
	 */
	public function getHTML( $tagName, $content, $attributes ){
		foreach( $attributes as $key => $value ){
			$attributes[$key] = sprintf('%s="%s"', $key, htmlspecialchars($value) );
		}

		return sprintf(
			'<%s%s>%s</%s>',
			$tagName,
			rtrim( ' ' . join(' ', $attributes) ),
			trim($content),
			$tagName
		);
	}

	/**
	 * get the limit, returns the class default
	 *
	 * @return int $limit Limit used by the pager query ( limit is the max items per page )
	 */
	public function getLimit(){
		if( null == $this->limit ){
			$this->limit = self::PAGER_LIMIT;
		}

		return $this->limit;
	}

	/**
	 * return the current offset. Offset is the "current position" in pager
	 * queries. so offset 5 means results starting at 6
	 *
	 * @return int $offset or 0
	 */
	public function getOffset(){
		if( null == $this->offset ){
			$this->offset = self::PAGER_OFFSET;
		}

		return $this->offset;
	}

	/**
	 * return the maximum of pager items
	 *
	 * @return int $max
	 */
	public function getMax(){
		if( null == $this->max ){
			$this->max = self::PAGER_MAX;
		}

		return $this->max;
	}

	/**
	 * return uri. a url may be given to prefix the pager with. url
	 * will be parsed so values in query string are preserved
	 *
	 * @return string $uri Uri passed to constructor or empty string
	 */
	public function getUri(){
		if( null == $this->uri ){
			$this->uri = '';
		}

		return $this->uri;
	}
}
